using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace HEFramework
{
    public interface IPool
    {
        bool IsFromPool { get; set; }
    }

    /// <summary>
    ///
    /// 对象
    /// 
    /// ----------------------------------------
    /// 作者 hep
    /// 创建时间：2023-11-28 18:01:44
    /// ----------------------------------------
    /// </summary>
    public abstract class Object : IPool
    {
        public override string ToString()
        {
            return "";
        }

        public string ToJson()
        {
            return "";
        }

        public byte[] ToBson()
        {
            return null;
        }

        public bool IsFromPool { get; set; }
    }

    /// <summary>
    ///
    /// 需释放对象
    /// 
    /// ----------------------------------------
    /// 作者 hep
    /// 创建时间：2023-11-29 13:48:29
    /// ----------------------------------------
    /// </summary>
    public abstract class DisposeObject : Object, IDisposable, ISupportInitialize
    {
        public virtual void Dispose()
        {
        }

        public virtual void BeginInit()
        {
        }

        public virtual void EndInit()
        {
        }
    }

    /// <summary>
    ///
    /// 对象生成器
    /// 
    /// ----------------------------------------
    /// 作者 hep
    /// 创建时间：2023-11-29 13:50:43
    /// ----------------------------------------
    /// </summary>
    public class ObjectGenerater : Singleton<ObjectGenerater>, ISingletonAwake
    {
        private Dictionary<Type, Queue<object>> pool;

        public void Awake()
        {
            lock (this)
            {
                this.pool = new Dictionary<Type, Queue<object>>();
            }
        }

        /// <summary>
        /// 获取（获取集合类型数据的时候记得清空再回收）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Fetch<T>() where T : class
        {
            return this.Fetch(typeof(T)) as T;
        }

        /// <summary>
        /// 获取（获取集合类型数据的时候记得清空再回收）
        /// </summary>
        /// <param name="_type"></param>
        /// <returns></returns>
        public object Fetch(Type _type)
        {
            lock (this)
            {
                Queue<object> queue = null;
                object o;
                if (!pool.TryGetValue(_type, out queue))
                {
                    o = Activator.CreateInstance(_type);
                }
                else if (queue.Count == 0)
                {
                    o = Activator.CreateInstance(_type);
                }
                else
                {
                    o = queue.Dequeue();
                }

                if (o is IPool iPool)
                {
                    iPool.IsFromPool = true;
                }

                return o;
            }
        }


        /// <summary>
        /// 回收
        /// </summary>
        /// <param name="_obj"></param>
        /// <param name="_force"></param>
        public void Recycle(object _obj, bool _force = false)
        {
            if (!_force)
            {
                if (_obj is IPool p)
                {
                    if (!p.IsFromPool)
                    {
                        return;
                    }

                    // 防止多次入池
                    p.IsFromPool = false;
                }
            }

            Type type = _obj.GetType();
            RecycleInner(type, _obj);
        }

        /// <summary>
        /// 回收【List】
        /// </summary>
        /// <param name="_obj"></param>
        /// <typeparam name="T"></typeparam>
        public void Recycle<T>(List<T> _obj)
        {
            _obj.Clear();
            Type type = _obj.GetType();
            RecycleInner(type, _obj);
        }

        /// <summary>
        /// 回收【Dictionary】
        /// </summary>
        /// <param name="_obj"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        public void Recycle<T, K>(Dictionary<T, K> _obj)
        {
            _obj.Clear();
            Type type = _obj.GetType();
            RecycleInner(type, _obj);
        }

        /// <summary>
        /// 回收【Stack】
        /// </summary>
        /// <param name="_obj"></param>
        /// <typeparam name="T"></typeparam>
        public void Recycle<T>(Stack<T> _obj)
        {
            _obj.Clear();
            Type type = _obj.GetType();
            RecycleInner(type, _obj);
        }


        /// <summary>
        /// 回收【Queue】
        /// </summary>
        /// <param name="_obj"></param>
        /// <typeparam name="T"></typeparam>
        public void Recycle<T>(Queue<T> _obj)
        {
            _obj.Clear();
            Type type = _obj.GetType();
            RecycleInner(type, _obj);
        }

        /// <summary>
        /// 内部回收
        /// </summary>
        /// <param name="_type"></param>
        /// <param name="_obj"></param>
        private void RecycleInner(Type _type, object _obj)
        {
            lock (this)
            {
                Queue<object> queue = null;
                if (!pool.TryGetValue(_type, out queue))
                {
                    queue = new Queue<object>();
                    pool.Add(_type, queue);
                }

                // 一种对象最大为1000个
                if (queue.Count > 1000)
                {
                    return;
                }

                queue.Enqueue(_obj);
            }
        }
    }
}